package the.guanzhong.delivery.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import javafx.concurrent.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.wisteria.framework.util.DateUtils;
import the.broccoli.setting.service.IParamsService;
import the.broccoli.uc.entity.User;
import the.broccoli.uc.service.IUserService;
import the.guanzhong.delivery.infrastructure.common.enums.DeliveryStatusEnum;
import the.guanzhong.delivery.infrastructure.mapper.DeliveryTaskMapper;
import the.guanzhong.delivery.interfaces.controller.req.TaskListReq;
import the.guanzhong.delivery.interfaces.controller.req.TaskReceiveReq;
import the.guanzhong.delivery.interfaces.controller.req.TaskTakeReq;
import the.guanzhong.delivery.interfaces.controller.resp.TaskItemResp;
import the.guanzhong.express.infrastructure.common.enums.OrderStatusEnum;
import the.guanzhong.express.infrastructure.mapper.ExpressOrderMapper;
import the.guanzhong.delivery.infrastructure.model.TaskDO;
import the.guanzhong.express.infrastructure.model.GoodsInfoDO;
import the.guanzhong.express.infrastructure.model.OrderDO;
import the.guanzhong.express.service.ExpressMpService;
import the.guanzhong.express.service.dto.OrderStatusUpdateMessageDTO;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 配送任务服务类
 */
@Slf4j
@Service
public class DeliveryTaskService {

    @Resource
    private DeliveryTaskMapper deliveryTaskMapper;

    @Resource
    private ExpressOrderMapper expressOrderMapper;

    @Resource
    private IUserService userService;

    @Resource
    private IParamsService paramsService;

    @Resource
    private ApiHelper pushApiHelper;

    @Resource
    private ExpressMpService expressMpService;

    /**
     * 获取配送任务列表
     * @param orderIdList   订单ID列表
     * @return
     */
    public List<TaskItemResp> selectBatchOrderIds(List<Integer> orderIdList) {
        List<TaskDO> datalist = deliveryTaskMapper.selectList(new LambdaQueryWrapper<TaskDO>()
                .in(TaskDO::getOrderId, new HashSet<>(orderIdList))
        );
        if (CollectionUtils.isEmpty(datalist)) {
            return null;
        }

        return datalist.stream().map(this::convertOf).collect(Collectors.toList());
    }


    /**
     * 查询配送任务列表
     * @param req   查询条件
     * @return
     */
    public List<TaskItemResp> list(TaskListReq req) {
        LambdaQueryWrapper<TaskDO> queryWrapper = new LambdaQueryWrapper<TaskDO>();
        if (req.getQueryType() == 1) {
            // 待接单，所有用户可看
            //queryWrapper.eq(TaskDO::getReceivingUserId, req.getUserId());
        } else if (req.getQueryType() == 2) {
            queryWrapper.eq(TaskDO::getReceivingUserId, req.getUserId());
        } else if (req.getQueryType() == 3) {
            queryWrapper.eq(TaskDO::getTakingUserId, req.getUserId());
        }
        queryWrapper.in(!CollectionUtils.isEmpty(req.getDeliveryStatusList()), TaskDO::getDeliveryStatus, req.getDeliveryStatusList());
        queryWrapper.orderByDesc(TaskDO::getOrderTime);
        queryWrapper.last(getLimitSql(req.getPageIndex(), req.getPageSize()));
        List<TaskDO> datalist = deliveryTaskMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(datalist)) {
            return null;
        }
        List<TaskItemResp> taskList = datalist.stream().map(this::convertOf).collect(Collectors.toList());

        List<String> userIdList = datalist.stream().map(TaskDO::getOrderUserId).collect(Collectors.toList());
        List<User> userList = userService.list(new LambdaQueryWrapper<User>()
                .in(User::getUserId, userIdList)
        );
        if (!CollectionUtils.isEmpty(userList)) {
            String imageUri = paramsService.getValue("DELIVERY_IMAGE_URI");
            Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getUserId, it -> it, (a, b) -> b));
            taskList.forEach(it -> {
                User user = userMap.get(it.getOrderUserId());
                if (user != null) {
                    it.setOrderUserName(user.getUserName());
                    it.setOrderUserAvatar(StringUtils.hasText(user.getAvatar()) ? imageUri + user.getAvatar() : "");
                }
            });
        }

        return taskList;
    }

    /**
     * 接单
     */
    public boolean receive(TaskReceiveReq req) {
        TaskDO task = deliveryTaskMapper.selectById(req.getDeliveryId());
        if (task == null) {
            return false;
        }

        Date receivingTime = new Date();
        int res = deliveryTaskMapper.update(null, new LambdaUpdateWrapper<TaskDO>()
                .set(TaskDO::getModifiedTime, LocalDateTime.now())
                .set(TaskDO::getModifiedId, req.getUserId())
                .set(TaskDO::getReceivingTime, receivingTime)
                .set(TaskDO::getReceivingUserId, req.getUserId())
                .set(TaskDO::getDeliveryStatus, DeliveryStatusEnum.WAITING_TAKING.getCode())

                .eq(TaskDO::getId, req.getDeliveryId())
        );
        if (res <= 0) {
            return false;
        }

        int r = expressOrderMapper.update(null, new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getModifiedTime, LocalDateTime.now())
                .set(OrderDO::getModifiedId, req.getUserId())
                .set(OrderDO::getOrderStatus, OrderStatusEnum.RECEIVED.getCode())

                .eq(OrderDO::getId, task.getOrderId())
        );
        if (r > 0) {
            User orderUser = userService.getById(task.getOrderUserId());
            if (orderUser != null && StringUtils.hasText(orderUser.getMpOpenId())) {
                OrderStatusUpdateMessageDTO dto = new OrderStatusUpdateMessageDTO();
                dto.setMpOpenId(orderUser.getMpOpenId());
                dto.setOrderId(task.getOrderId() + "");
                dto.setToAddress("发往 " + task.getToAddress());
                dto.setOrderStatusName("小哥正快马加鞭赶来取件");
                dto.setReceivingTime(receivingTime);
                expressMpService.notifyOrderStatusUpdate(dto);
            }
        }
        return r > 0;
    }

    /**
     * 取件
     */
    public boolean take(TaskTakeReq req) {
        TaskDO task = deliveryTaskMapper.selectById(req.getDeliveryId());
        if (task == null) {
            return false;
        }

        int res = deliveryTaskMapper.update(null, new LambdaUpdateWrapper<TaskDO>()
                .set(TaskDO::getModifiedTime, LocalDateTime.now())
                .set(TaskDO::getModifiedId, req.getUserId())
                .set(TaskDO::getTakingTime, LocalDateTime.now())
                .set(TaskDO::getTakingUserId, req.getUserId())
                .set(TaskDO::getDeliveryStatus, DeliveryStatusEnum.WAITING_HAULAGE.getCode())

                .eq(TaskDO::getId, req.getDeliveryId())
        );
        if (res <= 0) {
            return false;
        }

        return expressOrderMapper.update(null, new LambdaUpdateWrapper<OrderDO>()
                .set(OrderDO::getModifiedTime, LocalDateTime.now())
                .set(OrderDO::getModifiedId, req.getUserId())
                .set(OrderDO::getOrderStatus, OrderStatusEnum.TOOK.getCode())

                .eq(OrderDO::getId, task.getOrderId())
        ) > 0;
    }

    /**
     * 同步订单，创建配送任务
     * @param orderId
     */
    public void accept(Integer orderId) {
        OrderDO order = expressOrderMapper.selectById(orderId);
        if (order == null) {
            log.info("创建配送任务失败!订单不存在.OrderId:{}", orderId);
            return;
        }

        TaskDO delivery = new TaskDO();
        delivery.setOrderId(order.getId());
        delivery.setTenantId(order.getTenantId());
        delivery.setOrderUserId(order.getUserId());
        delivery.setOrderTime(order.getOrderTime());

        delivery.setFromTakeType(order.getFromTakeType());
        delivery.setFromShopId(order.getFromShopId());
        delivery.setFromShopName(order.getFromShopName());
        delivery.setFromLinkman(order.getFromLinkman());
        delivery.setFromPhone(order.getFromPhone());
        delivery.setFromAddress(order.getFromAddress());

        delivery.setToTakeType(order.getToTakeType());
        delivery.setToShopId(order.getToShopId());
        delivery.setToShopName(order.getToShopName());
        delivery.setToLinkman(order.getToLinkman());
        delivery.setToPhone(order.getToPhone());
        delivery.setToAddress(order.getToAddress());

        delivery.setHaulageWay(order.getTransWay());
        delivery.setGoodsInfo(order.getGoodsInfo());
        delivery.setDeliveryTime(new Date());
        delivery.setDeliveryStatus(DeliveryStatusEnum.WAITING_RECEIVING.getCode());

        deliveryTaskMapper.insert(delivery);

        try {
            GTNotification notification = new GTNotification();
            notification.setClickType("startapp");
            notification.setTitle("您有一个新订单,请及时接单");
            notification.setBody("取件地址:" + order.getFromShopName() + " " + order.getFromAddress() + ";下单时间:" + DateUtils.formatTime(order.getOrderTime()));

            PushMessage pushMessage = new PushMessage();
            pushMessage.setNetworkType(0);
            pushMessage.setNotification(notification);

            PushApi pushApi = pushApiHelper.creatApi(PushApi.class);
            PushDTO pushDTO = new PushDTO();
            pushDTO.setRequestId(System.nanoTime() + "");
            pushDTO.setPushMessage(pushMessage);

            ApiResult apiResult = pushApi.pushAll(pushDTO);
            log.info("订单任务推送, OrderId: {}, Result: {}", orderId, JSON.toJSONString(apiResult));
        } catch (Exception e) {
            log.error("推送配送任务异常, OrderId: {}, DeliveryId: {}", orderId, delivery.getId(), e);
        }
    }

    private String getLimitSql(Integer pageIndex, Integer pageSize) {
        int start = pageIndex == 0 ? 0 : pageIndex * pageSize + 1;
        int end = pageSize;
        return "limit " + start + "," + end;
    }

    private TaskItemResp convertOf(TaskDO source) {
        TaskItemResp target = new TaskItemResp();
        target.setDeliveryId(source.getId());
        target.setOrderId(source.getOrderId());
        target.setOrderUserId(source.getOrderUserId());
        target.setOrderUserName("");
        target.setOrderUserAvatar("");
        target.setOrderTime(DateUtils.formatTime(source.getOrderTime()));
        target.setFromShopName(source.getFromShopName());
        target.setFromAddress(source.getFromAddress());
        target.setToShopName(source.getToShopName());
        target.setToAddress(source.getToAddress());
        target.setHaulageWay(source.getHaulageWay());
        target.setDeliveryStatus(source.getDeliveryStatus());
        target.setTakingTime(DateUtils.formatTime(source.getTakingTime()));
        if (StringUtils.hasText(source.getGoodsInfo())) {
            target.setCargoList(JSON.parseArray(source.getGoodsInfo(), GoodsInfoDO.class));
        }
        target.setReceivingTime(source.getReceivingTime());
        target.setReceivingUserId(source.getReceivingUserId());
        return target;
    }
}
